/*
 * @Description: 类型判断
 * @Author: xinqiao lxq1990.0716@qq.com
 * @Date: 2023-07-20
 * @LastEditors: xinqiao lxq1990.0716@qq.com
 * @LastEditTime: 2025-03-20
 */

/** 自定义类型判断 */
export const is = (val: unknown, type: string) => Object.prototype.toString.call(val) === `[object ${type}]`

/** 判断字符串 */
export const isString = (val: unknown): boolean => is(val, 'String')

/** 判断数字 */
export const isNumber = (val: unknown): boolean => is(val, 'Number')

/** 判断布尔 */
export const isBoolean = (val: unknown): boolean => is(val, 'Boolean')

/** 判断undefined */
export const isUndefined = (val: unknown): boolean => val === undefined

/** 判断null */
export const isNull = (val: unknown): boolean => val === null

/** 判断对象 */
export const isObject = (val: any): boolean => val !== null && is(val, 'Object')

/** 判断数组 */
export const isArray = (val: any): boolean => val && Array.isArray(val)

/** 判断日期 */
export const isDate = (val: unknown): boolean => is(val, 'Date')

/** 判断函数 */
export const isFunction = (val: unknown): boolean => typeof val === 'function'

/** 判断异步函数 */
export const isAsyncFunction = (val: unknown): boolean => val instanceof Object.getPrototypeOf(async function () {}).constructor

/** 判断正则 */
export const isRegExp = (val: unknown): boolean => is(val, 'RegExp')

/** 判断空字符串 */
export const isEmptyString = (str: string) => str === ''

/** 判断空对象 */
export const isEmptyObject = (obj: Object) => Object.keys(obj).length === 0

/** 判断空数组 */
export const isEmptyArray = (arr: any[]) => arr.length === 0

/** 判断空变量（undefined、null、''、{}、[]等） */
export const isEmpty = (val: unknown) => {
  if (isUndefined(val)) return true
  if (isNull(val)) return true
  if (isString(val) && isEmptyString(val as string)) return true
  if (isObject(val) && isEmptyObject(val as Object)) return true
  if (isArray(val) && isEmptyArray(val as any[])) return true
  return false
}

/** 判断服务端（例如：nodejs） */
export const isServer = isUndefined(window)

/** 判断客户端（例如：浏览器、webview） */
export const isClient = !isUndefined(window)

/** 判断android */
export const isAndroid = navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1

/** 判断ios */
export const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)

export const isNullAndUnDef = (val: unknown): val is null | undefined => isUnDef(val) && isNull(val)

export const isUnDef = <T = unknown>(val?: T): val is T => !isDef(val)

export const isDef = <T = unknown>(val?: T): val is T => typeof val !== 'undefined'
